package com.lxj.ticket.service.common.util;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.collections4.CollectionUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 数学计算
 * @author 兴杰
 */
public class CommonMathUtil {

    // 计算所有的数组的交集
    @SafeVarargs
    public static List<Integer> getMixedList(List<Integer>... list) {
        if (list == null || list.length == 0) {
            return null;
        }
        if (list.length == 1) {
            return list[0];
        }

        List<Integer> res = null;
        for (int i = 0; i < list.length; i++) {
            List<Integer> item = list[i];
            if (i == 0) {
                res = JSON.parseArray(JSON.toJSONString(item), Integer.class);
            } else {
                res.retainAll(list[i]);
            }
        }
        return res;
    }

    @SafeVarargs
    public static List<PriceRangeDto> getPriceRange(List<PriceRangeDto>... priceList) {

        if (priceList.length == 0) {
            return null;
        }

        if (priceList.length == 1) {
            return priceList[0];
        }

        List<PriceRangeDto> res = null;
        for (int i = 0; i < priceList.length; i++) {

            List<PriceRangeDto> item = priceList[i];
            if (i == 0) {
                res = item;
            } else {
                List<PriceRangeDto> tempPrice = new ArrayList<>();
                res.forEach(item1 -> {

                    AtomicReference<BigDecimal> min = new AtomicReference<>(item1.getMinPrice());
                    AtomicReference<BigDecimal> max = new AtomicReference<>(item1.getMaxPrice());

                    AtomicReference<PriceRangeDto> priceRangeDto = new AtomicReference<>(new PriceRangeDto());
                    item.forEach(item2 -> {

                        if (max.get() != null && item2.getMaxPrice() != null) {

                            if (max.get().compareTo(item2.getMinPrice()) < 0 || min.get().compareTo(item2.getMaxPrice()) > 0) {
                                priceRangeDto.set(null);
                            } else if (min.get().compareTo(item2.getMinPrice()) == 0 && max.get().compareTo(item2.getMaxPrice()) == 0) {
                                // 值不动
                                if (priceRangeDto.get() == null) {
                                    priceRangeDto.set(new PriceRangeDto());
                                }
                            } else if (min.get().compareTo(item2.getMinPrice()) < 0 && max.get().compareTo(item2.getMinPrice()) == 0) {
//                                min.set(item2.getMinPrice());
                                priceRangeDto.set(null);
                            } else if (min.get().compareTo(item2.getMaxPrice()) == 0 && max.get().compareTo(item2.getMaxPrice()) > 0) {
//                                max.set(item2.getMaxPrice());
                                priceRangeDto.set(null);
                            } else if (min.get().compareTo(item2.getMinPrice()) < 0 && max.get().compareTo(item2.getMaxPrice()) < 0) {
                                min.set(item2.getMinPrice());
                                if (priceRangeDto.get() == null) {
                                    priceRangeDto.set(new PriceRangeDto());
                                }
                            } else if (min.get().compareTo(item2.getMinPrice()) > 0 && min.get().compareTo(item2.getMaxPrice()) < 0) {
                                max.set(item2.getMaxPrice());
                                if (priceRangeDto.get() == null) {
                                    priceRangeDto.set(new PriceRangeDto());
                                }
                            } else if (min.get().compareTo(item2.getMinPrice()) < 0 && max.get().compareTo(item2.getMaxPrice()) == 0) {
                                min.set(item2.getMinPrice());
                            } else if (min.get().compareTo(item2.getMinPrice()) == 0 && max.get().compareTo(item2.getMaxPrice()) > 0) {
                                max.set(item2.getMaxPrice());
                                if (priceRangeDto.get() == null) {
                                    priceRangeDto.set(new PriceRangeDto());
                                }
                            } else {
                                if (priceRangeDto.get() == null) {
                                    priceRangeDto.set(new PriceRangeDto());
                                }
                                min.set(item2.getMinPrice());
                                max.set(item2.getMaxPrice());
                            }

                        } else {

                            if (max.get() != null && item2.getMaxPrice() == null) {

                                if (min.get().compareTo(item2.getMinPrice()) < 0 && max.get().compareTo(item2.getMinPrice()) > 0) {
                                    min.set(item2.getMinPrice());
                                    if (priceRangeDto.get() == null) {
                                        priceRangeDto.set(new PriceRangeDto());
                                    }
                                } else {
                                    priceRangeDto.set(null);
                                }

                            } else if (max.get() == null && item2.getMaxPrice() != null) {
                                max.set(item2.getMaxPrice());
                                if (min.get().compareTo(item2.getMinPrice()) < 0) {
                                    min.set(item2.getMinPrice());
                                    if (priceRangeDto.get() == null) {
                                        priceRangeDto.set(new PriceRangeDto());
                                    }
                                } else {
                                    priceRangeDto.set(null);
                                }
                            } else {
                                if (min.get().compareTo(item2.getMinPrice()) < 0) {
                                    min.set(item2.getMinPrice());
                                }
                                if (priceRangeDto.get() == null) {
                                    priceRangeDto.set(new PriceRangeDto());
                                }
                            }

//                            if (max.get() == null) {
//                                if (item2.getMaxPrice() != null) {
//                                    max.set(item2.getMaxPrice());
//                                }
//                                if (min.get().compareTo(item2.getMinPrice()) < 0) {
//                                    min.set(item2.getMinPrice());
//                                }
//                            }
//                            if (item2.getMaxPrice() == null) {
//                                if (min.get().compareTo(item2.getMinPrice()) < 0) {
//                                    min.set(item2.getMinPrice());
//                                }
//                            }
                        }
//                        if (min.get().compareTo(item2.getMinPrice()) < 0) {
//
//                            min.set(item2.getMinPrice());
//                        }
//                        if (max.get() == null) {
//                            if (item2.getMaxPrice() != null) {
//                                max.set(item2.getMaxPrice());
//                            }
//                        } else {
//                            if (item2.getMaxPrice() != null && max.get().compareTo(item2.getMaxPrice()) > 0) {
//                                    max.set(item2.getMaxPrice());
//                            }
//                        }
                        if (priceRangeDto.get() != null) {
                            priceRangeDto.get().setMinPrice(min.get());
                            priceRangeDto.get().setMaxPrice(max.get());
                            tempPrice.add(priceRangeDto.get());
                        }
                    });
                });

                res = tempPrice;
            }
        }

        Set<String> allPriceStr = new HashSet<>();
        List<PriceRangeDto> resFilter = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(res)) {
            res.forEach(item -> {
                String key = (item.getMinPrice() == null ? "" : item.getMinPrice().toString()) + "-" + (item.getMaxPrice() == null ? "" : item.getMaxPrice());
                if (!allPriceStr.contains(key)) {
                    resFilter.add(item);
                    allPriceStr.add(key);
                }
            });
        }

        return resFilter;
    }

    public static void main(String[] args) {


//        List<Integer> one = new ArrayList<>();
//        one.add(1);
//        one.add(2);
//
//        List<Integer> one = Arrays.asList(1, 2, 3);
//        List<Integer> two = new ArrayList<>();
//        two.add(2);
//        two.add(3);
//        List<Integer> two = Arrays.asList(2, 3, 4);
//        List<Integer> mixedList = getMixedList();
//        System.out.println(mixedList);
//
//        PriceRangeDto one = new PriceRangeDto()
//                .setMinPrice(new BigDecimal("10"))
//                .setMaxPrice(new BigDecimal("20"));
//
//        PriceRangeDto two = new PriceRangeDto()
//                .setMinPrice(new BigDecimal("20"))
//                .setMaxPrice(new BigDecimal("30"));
//
//        PriceRangeDto three = new PriceRangeDto()
//                .setMinPrice(new BigDecimal("10"))
//                .setMaxPrice(new BigDecimal("20"));
//
//        PriceRangeDto four = new PriceRangeDto()
//                .setMinPrice(new BigDecimal("20"))
//                .setMaxPrice(new BigDecimal("30"));
//
//        PriceRangeDto five = new PriceRangeDto()
//                .setMinPrice(new BigDecimal("30"))
//                .setMaxPrice(new BigDecimal("40"));
//
//        PriceRangeDto six = new PriceRangeDto()
//                .setMinPrice(new BigDecimal("50"))
//                .setMaxPrice(null);
//        String key = six.getMinPrice() == null ? "null" : six.getMinPrice().toString() + "-" + (six.getMaxPrice() == null ? "null" : six.getMaxPrice());
//
//        System.err.println(key);
//        List<List<PriceRangeDto>> testList = new ArrayList<>();
//        List<PriceRangeDto> oneList = Arrays.asList(one, two, six);
//        List<PriceRangeDto> twoList = Arrays.asList(six, one);
//        testList.add(oneList);
//        testList.add(twoList);
//        List<PriceRangeDto> priceRangeNew = getPriceRangeNew(testList);
//        System.err.println("结果为：" + priceRangeNew);

//        List<PriceRangeDto> priceRange = getPriceRange(Arrays.asList(one, two, six), Arrays.asList(one, six));
//        System.out.println("价格对比结果为：" + priceRange);

//        Random random = new Random();
//
//        while (true) {
//            int i = random.nextInt(31);
//            if (i < 0 || i > 31) {
//                System.err.println("超出了范围");
//                break;
//            }
//        }

//        BigDecimal one = new BigDecimal("20");
//        BigDecimal two = new BigDecimal("1");
//        int i = one.compareTo(two);
//
//        System.out.println("结果为" + i);
        dealPriceRange(new ArrayList<>());
    }

    private static List<PriceRangeDto> getPriceRangeNew(List<List<PriceRangeDto>> priceList) {
        if (CollectionUtils.isEmpty(priceList)) {
            return new ArrayList<>();
        }

        if (priceList.size() == 1) {
            return priceList.get(0);
        }

        List<List<String>> allKeys = new ArrayList<>();
        priceList.forEach(item -> {
            allKeys.add(item.stream().map(item2 -> (item2.getMinPrice() == null ? "null" : item2.getMinPrice().toString()) + "-" + (item2.getMaxPrice() == null ? "null" : item2.getMaxPrice())).collect(Collectors.toList()));
        });

        List<String> temp = allKeys.get(0);
        for (List<String> allKey : allKeys) {
            temp.retainAll(allKey);
        }

        if (CollectionUtils.isEmpty(temp)) {
            return new ArrayList<>();
        }
        List<PriceRangeDto> collect = temp.stream().map(item -> {
            PriceRangeDto resItem = new PriceRangeDto();
            String[] split = item.split("-");
            if (split.length == 2) {
                if (!"null".equals(split[0])) {
                    resItem.setMinPrice(new BigDecimal(split[0]));
                }
                if (!"null".equals(split[1])) {
                    resItem.setMaxPrice(new BigDecimal(split[1]));
                }
                return resItem;
            }
            return null;

        }).filter(Objects::nonNull).collect(Collectors.toList());

        return collect;
    }

    private static List<PriceRangeDto> dealPriceRange(List<List<PriceRangeDto>> priceList) {


        // [1,2] [2,3]
        // [2,3] [3,4]
        List<PriceRangeDto> all = new ArrayList<>();
        all.add(new PriceRangeDto().setMinPrice(new BigDecimal("10"))
                .setMaxPrice(new BigDecimal("20")));

        all.add(new PriceRangeDto().setMinPrice(new BigDecimal("19"))
                .setMaxPrice(new BigDecimal("30")));

        all.add(new PriceRangeDto().setMinPrice(new BigDecimal("15"))
                .setMaxPrice(new BigDecimal("40")));
        BigDecimal min = null;
        BigDecimal max = null;
        boolean hasRange = true;
        for (int i = 0; i < all.size(); i++) {

            PriceRangeDto item = all.get(i);
            if (i == 0) {
                min = item.getMinPrice();
                max = item.getMaxPrice();
            } else {
                if (max == null && item.getMaxPrice() != null) {
                    max = item.getMaxPrice();
                }
                if (min == null && item.getMinPrice() != null) {
                    min = item.getMinPrice();
                } else if (min != null && item.getMinPrice() != null) {
                    if (min.compareTo(item.getMinPrice()) < 0) {
                        min = item.getMinPrice();
                    }
                }

                if (min != null && max != null) {
                    if (min.compareTo(max) >= 0) {
                        hasRange = false;
                        break;
                    }
                }

            }
        }

        if (hasRange) {
            System.out.println("结果为：最小值：" + min + " 最大值为：" + max);
        } else {
            System.out.println("没有交集");
        }
        return new ArrayList<>();
    }
}

@Data
@Accessors(chain = true)
class PriceRangeDto implements Serializable {

    /**
     * 最小值
     */
    private BigDecimal minPrice = new BigDecimal("0");

    /**
     * 最大值
     */
    private BigDecimal maxPrice;

    /**
     * 分隔符
     */
    private String separator;

}
